package gen;

import gen.model.IDatatype;
import gen.model.ModelAttribute;
import gen.model.ModelClass;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class GenClassHelper {
	static void generateClass(ModelClass modelClass, Map<String, IDatatype> objects) throws IOException {
		String package_ = "ar.com.coonocer.joy.mdg.xmi." + modelClass.getLabel() + ".impl";
		//
		File f = new File(GenerateModelClasses.ROOT + "/" + package_.replace('.', '/') + "/" + modelClass.getName() + "Impl.java");
		f.getParentFile().mkdirs();
		FileWriter fw = new FileWriter(f);
		//
		fw.write("package " + package_ + ";\r\n");
		//
		fw.write("import ar.com.coonocer.joy.mdg.xmi.core.Class;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.model.Package;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.behavior.Object;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.behavior.Exception;\r\n");
		fw.write("\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.activity.*;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.behavior.*;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.collab.*;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.core.*;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.datatype.*;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.usecase.*;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.model.*;\r\n");
		fw.write("import ar.com.coonocer.joy.mdg.xmi.state.*;\r\n");
		fw.write("import java.util.List;\r\n");
		fw.write("import java.util.ArrayList;\r\n");
		//
		fw.write("public class " + modelClass.getName() + "Impl implements " + modelClass.getName());
		if (!modelClass.supertypes.isEmpty()) {
			//
			for (String supertypeId : modelClass.supertypes) {
				fw.write(",");
				fw.write(GenerateModelClasses.getTypeName(supertypeId, objects));
			}
		}
		fw.write("{");
		fw.write("\r\n");
		//
		generateClassMethods(fw, modelClass, objects);
		//
		fw.write("}");
		fw.close();
	}

	private static void generateClassMethods(FileWriter fw, ModelClass modelClass, Map<String, IDatatype> objects) throws IOException {
		Set<ModelAttribute> atts = findAttributes(modelClass, objects);
		for (ModelAttribute att : atts) {
			//
			String singulartype = GenerateModelClasses.getTypeName(att.type, objects);
			String type = GenerateModelClasses.generateDataTypeForMany(att, objects);
			//
			fw.write("\r\n");
			// attribute
			if (att.many) {
				fw.write("	private " + type + " " + GenerateModelClasses.getVariableName(att.name) + " = new ArrayList<" + singulartype + ">();\r\n");
			} else {
				fw.write("	private " + type + " " + GenerateModelClasses.getVariableName(att.name) + ";\r\n");
			}
			// getter
			fw.write("	public " + type + " get" + GenerateModelClasses.upperInitial(att.name) + "(){\r\n");
			fw.write("	return " + GenerateModelClasses.getVariableName(att.name) + ";\r\n");
			fw.write("	}\r\n");
			// setter
			fw.write("	public void set" + GenerateModelClasses.upperInitial(att.name) + "(" + type + " " + GenerateModelClasses.getVariableName(att.name) + "){\r\n");
			fw.write("	this." + GenerateModelClasses.getVariableName(att.name) + "=" + GenerateModelClasses.getVariableName(att.name) + ";\r\n");
			fw.write("	}\r\n");
			//
		}
	}

	private static Set<ModelAttribute> findAttributes(ModelClass modelClass, Map<String, IDatatype> objects) {
		Set<ModelAttribute> atts = new HashSet<ModelAttribute>();
		//
		for (ModelAttribute att : modelClass.attributes) {
			atts.add(att);
		}
		//
		for (String typeId : modelClass.supertypes) {
			ModelClass supertype = (ModelClass) objects.get(typeId);
			if (supertype == null) {
				throw new RuntimeException("Error, supertype not found: " + typeId + ", for class: " + modelClass.getName());
			}
			if (supertype != null) {
				atts.addAll(findAttributes(supertype, objects));
			}
		}
		//
		return atts;
	}

}
